package cn.iocoder.an.module.mold.service.drawingnobom;

import cn.hutool.core.collection.CollUtil;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.iocoder.an.module.mold.controller.admin.drawingnobom.vo.*;
import cn.iocoder.an.module.mold.dal.dataobject.drawingnobom.DrawingNoBomDO;
import cn.iocoder.an.framework.common.pojo.PageResult;
import cn.iocoder.an.framework.common.pojo.PageParam;
import cn.iocoder.an.framework.common.util.object.BeanUtils;

import cn.iocoder.an.module.mold.dal.mysql.drawingnobom.DrawingNoBomMapper;

import static cn.iocoder.an.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.an.module.mold.enums.ErrorCodeConstants.*;

/**
 * 模具图号BOM Service 实现类
 *
 * @author ykk
 */
@Service
@Validated
public class DrawingNoBomServiceImpl implements DrawingNoBomService {

    @Resource
    private DrawingNoBomMapper drawingNoBomMapper;

    @Override
    public Long createDrawingNoBom(DrawingNoBomSaveReqVO createReqVO) {
        // 校验父主键的有效性
        validateParentDrawingNoBom(null, createReqVO.getPid());
        // 校验编号的唯一性
        validateDrawingNoBomCodeUnique(null, createReqVO.getPid(), createReqVO.getCode());

        // 插入
        DrawingNoBomDO drawingNoBom = BeanUtils.toBean(createReqVO, DrawingNoBomDO.class);
        drawingNoBomMapper.insert(drawingNoBom);

        // 返回
        return drawingNoBom.getId();
    }

    @Override
    public void updateDrawingNoBom(DrawingNoBomSaveReqVO updateReqVO) {
        // 校验存在
        validateDrawingNoBomExists(updateReqVO.getId());
        // 校验父主键的有效性
        validateParentDrawingNoBom(updateReqVO.getId(), updateReqVO.getPid());
        // 校验编号的唯一性
        validateDrawingNoBomCodeUnique(updateReqVO.getId(), updateReqVO.getPid(), updateReqVO.getCode());

        // 更新
        DrawingNoBomDO updateObj = BeanUtils.toBean(updateReqVO, DrawingNoBomDO.class);
        drawingNoBomMapper.updateById(updateObj);
    }

    @Override
    public void deleteDrawingNoBom(Long id) {
        // 校验存在
        validateDrawingNoBomExists(id);
        // 校验是否有子模具图号BOM
        if (drawingNoBomMapper.selectCountByPid(id) > 0) {
            throw exception(DRAWING_NO_BOM_EXITS_CHILDREN);
        }
        // 删除
        drawingNoBomMapper.deleteById(id);
    }


    private void validateDrawingNoBomExists(Long id) {
        if (drawingNoBomMapper.selectById(id) == null) {
            throw exception(DRAWING_NO_BOM_NOT_EXISTS);
        }
    }

    private void validateParentDrawingNoBom(Long id, Long pid) {
        if (pid == null || DrawingNoBomDO.PID_ROOT.equals(pid)) {
            return;
        }
        // 1. 不能设置自己为父模具图号BOM
        if (Objects.equals(id, pid)) {
            throw exception(DRAWING_NO_BOM_PARENT_ERROR);
        }
        // 2. 父模具图号BOM不存在
        DrawingNoBomDO parentDrawingNoBom = drawingNoBomMapper.selectById(pid);
        if (parentDrawingNoBom == null) {
            throw exception(DRAWING_NO_BOM_PARENT_NOT_EXITS);
        }
        // 3. 递归校验父模具图号BOM，如果父模具图号BOM是自己的子模具图号BOM，则报错，避免形成环路
        if (id == null) { // id 为空，说明新增，不需要考虑环路
            return;
        }
        for (int i = 0; i < Short.MAX_VALUE; i++) {
            // 3.1 校验环路
            pid = parentDrawingNoBom.getPid();
            if (Objects.equals(id, pid)) {
                throw exception(DRAWING_NO_BOM_PARENT_IS_CHILD);
            }
            // 3.2 继续递归下一级父模具图号BOM
            if (pid == null || DrawingNoBomDO.PID_ROOT.equals(pid)) {
                break;
            }
            parentDrawingNoBom = drawingNoBomMapper.selectById(pid);
            if (parentDrawingNoBom == null) {
                break;
            }
        }
    }

    private void validateDrawingNoBomCodeUnique(Long id, Long pid, String code) {
        DrawingNoBomDO drawingNoBom = drawingNoBomMapper.selectByPidAndCode(pid, code);
        if (drawingNoBom == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的模具图号BOM
        if (id == null) {
            throw exception(DRAWING_NO_BOM_CODE_DUPLICATE);
        }
        if (!Objects.equals(drawingNoBom.getId(), id)) {
            throw exception(DRAWING_NO_BOM_CODE_DUPLICATE);
        }
    }

    @Override
    public DrawingNoBomDO getDrawingNoBom(Long id) {
        return drawingNoBomMapper.selectById(id);
    }

    @Override
    public List<DrawingNoBomDO> getDrawingNoBomList(DrawingNoBomListReqVO listReqVO) {
        return drawingNoBomMapper.selectList(listReqVO);
    }

}